package top.tenebrous.yzl.chat.config;

import cn.dev33.satoken.stp.StpInterface;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import top.tenebrous.yzl.basic.enums.DeleteStatus;
import top.tenebrous.yzl.chat.domain.system.SysMenu;
import top.tenebrous.yzl.chat.domain.system.SysRole;
import top.tenebrous.yzl.chat.domain.system.SysRoleMenu;
import top.tenebrous.yzl.chat.domain.system.SysUserRole;
import top.tenebrous.yzl.chat.service.system.ISysMenuService;
import top.tenebrous.yzl.chat.service.system.ISysRoleMenuService;
import top.tenebrous.yzl.chat.service.system.ISysRoleService;
import top.tenebrous.yzl.chat.service.system.ISysUserRoleService;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 自定义权限加载接口实现类
 * 根据用户id查询其权限及角色（查询应为统一方法）
 * @author yazhang6
 */
@Slf4j
@Component
public class StpInterfaceImpl implements StpInterface {

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysRoleMenuService roleMenuService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysUserRoleService userRoleService;

    /**
     * 返回一个账号所拥有的权限码集合 
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        log.info("用户[{}][{}]登录，加载用户权限开始", loginId, loginType);
        Long userId = (Long) loginId;
        List<String> list = new ArrayList<>();
        // 查询该用户对应的角色id
        List<SysUserRole> roles = userRoleService.list(new LambdaQueryWrapper<SysUserRole>()
                .select(SysUserRole::getRoleId)
                .eq(SysUserRole::getUserId, userId)
                .eq(SysUserRole::getIsDeleted, DeleteStatus.DELETE_NO.getStatus())
        );
        Set<Long> roleIds = roles.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(roleIds)) {
            log.info("用户[{}][{}]登录，加载用户权限结束, 用户未配置角色信息", loginId, loginType);
            return list;
        }

        // 查询该用户角色对应的菜单id
        List<SysRoleMenu> roleMenus = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>()
                .select(SysRoleMenu::getMenuId)
                .in(SysRoleMenu::getRoleId, roleIds)
                .eq(SysRoleMenu::getIsDeleted, DeleteStatus.DELETE_NO.getStatus())
        );
        Set<Long> menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(menuIds)) {
            log.info("用户[{}][{}]登录，加载用户权限结束, 用户未配置菜单信息", loginId, loginType);
            return list;
        }
        // 查询该用户角色对应的菜单信息
        List<SysMenu> menus = menuService.list(new LambdaQueryWrapper<SysMenu>()
                .in(SysMenu::getId, menuIds)
                .eq(SysMenu::getIsDeleted, DeleteStatus.DELETE_NO.getStatus())
        );
        if (CollectionUtils.isEmpty(menus)) {
            log.info("用户[{}][{}]登录，加载用户权限结束, 用户菜单不存在", loginId, loginType);
            return list;
        }
        // 获取该用户菜单下的权限标识
        List<String> permitMarks = menus.stream().map(SysMenu::getPermitMark).filter(item -> !StringUtils.isNotBlank(item)).collect(Collectors.toList());
        list.addAll(permitMarks);
        log.info("用户[{}][{}]登录，加载用户权限结束 用户菜单权限[{}]", loginId, loginType, JSON.toJSONString(permitMarks));
        return list;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        log.info("用户[{}][{}]登录，加载用户角色开始", loginId, loginType);
        List<String> list = new ArrayList<>();
        Long userId = (Long) loginId;
        // 查询该用户对应的角色id
        List<SysUserRole> roles = userRoleService.list(new LambdaQueryWrapper<SysUserRole>()
                .select(SysUserRole::getRoleId)
                .eq(SysUserRole::getUserId, userId)
                .eq(SysUserRole::getIsDeleted, DeleteStatus.DELETE_NO.getStatus())
        );
        Set<Long> roleIds = roles.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(roleIds)) {
            log.info("用户[{}][{}]登录，加载用户权限结束, 用户未配置角色信息", loginId, loginType);
            return list;
        }

        // 获取角色信息
        List<SysRole> sysRoles = roleService.list(new LambdaQueryWrapper<SysRole>()
                .in(SysRole::getId, roleIds)
                .eq(SysRole::getIsDeleted, DeleteStatus.DELETE_NO.getStatus())
        );
        if (CollectionUtils.isEmpty(sysRoles)) {
            log.info("用户[{}][{}]登录，加载用户权限结束, 用户角色不存在", loginId, loginType);
            return list;
        }
        List<String> roleNames = sysRoles.stream().map(SysRole::getRoleName).filter(item -> !StringUtils.isNotBlank(item)).collect(Collectors.toList());
        list.addAll(roleNames);
        log.info("用户[{}][{}]登录，加载用户角色结束 用户角色[{}]", loginId, loginType, JSON.toJSONString(list));
        return list;
    }

}
